package com.tools.web.http;

import com.tools.common.object.C;
import com.tools.common.object.Note;
import com.tools.common.object.ObjKit;
import com.tools.common.object.string.StrKit;
import org.springframework.web.servlet.HandlerMapping;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Enumeration;
import java.util.Map;

/**
 * 来自 HTTP 请求中的数据放在该请求的哪些地方"
 * */
@Note("来自 HTTP 请求中的数据放在该请求的哪些地方")
public enum HttpDataFromEnum implements HttpDataFrom {

    HEADER("header") {
        @Override
        public String getData(HttpServletRequest request, String name) {
            return private_handleHeader(request, name);
        }

        @Override
        public void setData(HttpServletRequest request, HttpServletResponse response, String name, Object value) {
            private_setDataInHeader(response, name, value);
        }
    },


    PARAM("param") {
        @Override
        public String getData(HttpServletRequest request, String name) {
            return request.getParameter(name);
        }

        @Override
        public void setData(HttpServletRequest request, HttpServletResponse response, String name, Object value) {
            Map<String, Object> ownParamMap = this.getOrSetOwnDataMap(request);
            ownParamMap.put(name, value);
            request.setAttribute(OWN_DATA_MAP, ownParamMap);
        }
    },


    PATH("path") {
        @Override
        public String getData(HttpServletRequest request, String name) {
            return private_handlePath(request, name);
        }

        @Override
        public void setData(HttpServletRequest request, HttpServletResponse response, String name, Object value) {
            Map<String, Object> ownParamMap = this.getOrSetOwnDataMap(request);
            ownParamMap.put(name, value);
            request.setAttribute(OWN_DATA_MAP, ownParamMap);
        }
    }
    ;

    HttpDataFromEnum(String value) {
        this.value = value;
    }

    private final String value;



    public String getValue() {
        return value;
    }

    /* ************************************************************************************************************
     *
     *
     *          功能方法
     *
     * ************************************************************************************************************
     * */

    @Override
    public <T> T getData(HttpServletRequest request, String name, C<T> valueType) {
        String data = this.getData(request, name);
        return (T) ObjKit.stringToRealValue(data, valueType);
    }


    public static String getData(HttpDataFromEnum instance, HttpServletRequest request, String name) {
        if(instance == null) return null;
        return instance.getData(request, name);
    }

    public static <T> T getData(HttpDataFromEnum instance, HttpServletRequest request, String name, C<T> valueType) {
        if(instance == null) return null;
        return instance.getData(request, name, valueType);
    }


    @Note("安全地根据 value 返回枚举实例。不会抛异常")
    public static HttpDataFromEnum getEnumSafe(String value) {
        if(value == null) return null;
        switch (value.toLowerCase()) {
            case "header": return HEADER;
            case "param": return PARAM;
            case "path": return PATH;
            default: return null;
        }
    }

    @Note("直接根据 value 返回枚举实例。获取不到会抛异常")
    public static HttpDataFromEnum getEnum(String value) {
        HttpDataFromEnum instance = getEnumSafe(value);
        if(instance != null) return instance;
        throw new IllegalArgumentException("没有找到值为 " + value + " 的枚举实例");
    }


    /* ************************************************************************************************************
     *
     *
     *          私有逻辑
     *
     * ************************************************************************************************************
     * */


    @Note("获取指定名称的请求头数据，若是多个则用【,】拼接")
    private static String private_handleHeader(HttpServletRequest request, String name) {
        Enumeration<String> headers = request.getHeaders(name);
        if(headers != null) {
            StringBuilder builder = new StringBuilder();
            while (headers.hasMoreElements()) {
                builder.append(',').append(headers.nextElement());
            }
            return builder.length() != 0
                    ? builder.substring(1)
                    : builder.toString();
        }
        return null;
    }


    @Note("将 value 设置进响应头里")
    private static void private_setDataInHeader(HttpServletResponse response, String name, Object value) {
        if(name == null || name.isEmpty() || value == null) return;
        String separator = ",";
        if(value instanceof Iterable) {
            String newValue = StrKit.toString(separator, (Iterable<?>) value);
            response.setHeader(name, newValue);
            return;
        }
        String s = StrKit.arrayToString(separator, value);
        if(!s.isEmpty()) {
            response.setHeader(name, s);
            return;
        }
        response.setHeader(name, value.toString());
    }


    @Note("获取 Path 路径中的参数名称对应的 value 值（类型是字符串）")
    private static String private_handlePath(HttpServletRequest request, String name) {
        return ((Map<String, String>) request.getAttribute(HandlerMapping.URI_TEMPLATE_VARIABLES_ATTRIBUTE))
                .get(name);
    }

}
